﻿using System;
using System.Collections.Generic;


namespace testGridMap
{
  public class EarthShade
  {


    protected DateTime _datum = DateTime.Now;





    protected int computePointLightIntensity(NormalVector solarRayVector, NormalVector earthPointNormalVector)
    {

      // compute algle between two 3d vectors
      double fi = Math.Acos(
        ((solarRayVector.X * earthPointNormalVector.X) +
        (solarRayVector.Y * earthPointNormalVector.Y) +
        (solarRayVector.Z * earthPointNormalVector.Z)) /
        (
        Math.Sqrt(
        Math.Pow(solarRayVector.X, 2) +
        Math.Pow(solarRayVector.Y, 2) +
        Math.Pow(solarRayVector.Z, 2)) *
        Math.Sqrt(
        Math.Pow(earthPointNormalVector.X, 2) +
        Math.Pow(earthPointNormalVector.Y, 2) +
        Math.Pow(earthPointNormalVector.Z, 2))
        ));


      // some adjustments..
      fi = Math.Abs(Radians2Degrees(fi));
      if (fi >= 250)
        fi = 360 - 250;

      // if angle is more than 100deg, it is full darkness
      if (fi > 100)
        return 0;
      else
        // else return intensity 0 - 255
        return 255 - (int)((255.0 / 100.0) * fi);

    }




    // 0 is Greenwich
    protected NormalVector computeLightRayVector(DateTime myDate)
    { 
      
      double verticalAngle;
      double horizontalAngle;
      int days;

      // should be always aprox. 91.25
      if(myDate.Month >= 3 && myDate.Day >= 21 && myDate.Month <= 6 && myDate.Day <= 20)
      {
        // 1 st period
        // 23.5 deg is decline angle
        days = new DateTime(myDate.Year, 6, 20).Subtract(new DateTime(myDate.Year, 3, 21)).Days;
        verticalAngle = (23.5 / days) * myDate.Subtract(new DateTime(myDate.Year, 3, 21)).Days;
      }

      else if (myDate.Month >= 6 && myDate.Day >= 21 && myDate.Month <= 9 && myDate.Day <= 22)
      {
        // 2 nd period
        // 23.5 deg is decline angle
        days = new DateTime(myDate.Year, 9, 22).Subtract(new DateTime(myDate.Year, 6, 21)).Days;
        verticalAngle = 23.5 - ((23.5 / days) * myDate.Subtract(new DateTime(myDate.Year, 6, 21)).Days);
      }
      else if (myDate.Month >= 9 && myDate.Day >= 23 && myDate.Month <= 12 && myDate.Day <= 21)
      {
        // 3 rd period
        // 23.5 deg is decline angle
        days = new DateTime(myDate.Year, 12, 21).Subtract(new DateTime(myDate.Year, 9, 23)).Days;
        verticalAngle = (23.5 / days) * myDate.Subtract(new DateTime(myDate.Year, 9, 23)).Days;
      }
      else 
      {
        // 4 th period
        // 23.5 deg is decline angle
        days = 9;
        days += new DateTime(myDate.Year, 3, 21).Subtract(new DateTime(myDate.Year, 1, 1)).Days;
        if (myDate.Month == 12)
          verticalAngle = (23.5 / days) * (myDate.Day - 22);
        else
          verticalAngle = (23.5 / days) * (9 + myDate.Subtract(new DateTime(myDate.Year, 1, 1)).Days);
      }

      //throw new NotFiniteNumberException();

      horizontalAngle = (24 / 360) * myDate.Hour;
      horizontalAngle -= 180;

      NormalVector n = new NormalVector();

      n.X = Math.Sin(horizontalAngle);
      n.Y = Math.Cos(horizontalAngle);
      n.Z = Math.Sin(verticalAngle);

      return n;

    }



    private const double R2D = 180 / Math.PI;
    private const double D2R = Math.PI / 180;


    private static double Radians2Degrees(double rad)
    {
      return (R2D * rad);
    }

    private static double Degrees2Radians(double deg)
    {
      return (D2R * deg);
    }
  }
}
